# coding=utf-8

from app.cores.dictionaries import DISPATCHER_TYPE, REPORT_RESULT
from app.cores.dispatcher import AbstractCaseDispatcher
from app.cores.case.sql.request import make_request
from app.cores.case.base.script import exec_postprocessor_script, exec_preprocessor_script
from app.cores.case.base.last_result import LastResult
from app.cores.case.base.expectation import get_expectations_result


class SQLCaseDispatcher(AbstractCaseDispatcher):
    def __init__(self, case, dispatcher_type=DISPATCHER_TYPE.DEBUG, logger=None, dispatcher=None):
        """
        :param case: 单个SQLCase案例请求数据
        :type case: Case
        :param dispatcher_type: 标识构建是通过单独案例调试(DISPATCHER_TYPE.DEBUG)还是通过模块/项目构建测试(DISPATCHER_TYPE.BUILD)
        :type dispatcher_type: str
        :param logger: 当dispatcher_type为DISPATCHER_TYPE.BUILD时，需要传入调度日志
        :type logger: DispatcherLogger
        :param dispatcher: 当dispatcher_type为DISPATCHER_TYPE.BUILD时，需要传入调度数据
        :type dispatcher: Dispatcher
        """
        super().__init__(case=case, dispatcher_type=dispatcher_type, logger=logger, dispatcher=dispatcher)
        # 请求对象
        self.request_ = None

        # 后处理脚本断言结果
        self.postprocessor_failure = None
        # 后处理脚本错误信息
        self.postprocessor_failure_message = None

        # 组件期望断言结果
        self.expectations_result = False

        # sql请求字段
        self.host = None
        self.port = None
        self.connect_timeout = None
        self.user = None
        self.password = None
        self.db_type = None
        self.sql = None
        self.charset = None
        self.expectation_logic = None
        self.postprocessor_script = None
        self.expectations = None

    def set_up(self):
        super().set_up()
        # 预处理脚本执行
        preprocessor_script = self.case.specific_case.preprocessor_script_
        exec_preprocessor_script(
            source=preprocessor_script,
            project_id=self.case.scene.module.project_id,
            log=self.dispatcher_logger.logger,
        )

    def _load_data(self):  # 在execute执行开始时执行
        super()._load_data()
        self.host = self.case.specific_case.host_
        self.port = self.case.specific_case.port_
        self.connect_timeout = self.case.specific_case.connect_timeout_
        self.user = self.case.specific_case.user_
        self.password = self.case.specific_case.password_
        self.db_type = self.case.specific_case.db_type
        self.sql = self.case.specific_case.sql_
        self.charset = self.case.specific_case.charset_
        self.expectation_logic = self.case.specific_case.expectation_logic
        self.postprocessor_script = self.case.specific_case.postprocessor_script_
        self.expectations = self.case.specific_case.expectations

    def execute(self):
        super().execute()
        # 请求发送
        self.request_ = make_request(host=self.host, port=self.port, user=self.user, password=self.password,
                                     connect_timeout=self.connect_timeout, charset=self.charset, sql=self.sql,
                                     db_type=self.db_type)
        self.request_.send()

    def tear_down(self):
        super().tear_down()
        # 更新结果数据1
        LastResult.update_request_and_response_to_last_result(
            request_headers=self.request_.request_headers,
            request_body=self.request_.request_body,
            response_headers=self.request_.response_headers,
            response_body=self.request_.response_body,
        )
        # 后处理脚本执行
        self.postprocessor_failure, self.postprocessor_failure_message = exec_postprocessor_script(
            source=self.postprocessor_script,
            project_id=self.case.scene.module.project_id,
            case=self.case,
            log=self.dispatcher_logger.logger,
        )
        # 进行期望判断
        self.expectations_result = get_expectations_result(expectations=self.expectations,
                                                           request=self.request_,
                                                           expectation_logic=self.expectation_logic)

    def run(self):
        super().run()
        log_text = self.dispatcher_logger.get_string_buffer()
        return dict(
            request_=self.request_,
            expectations_result=self.expectations_result,
            expectations=self.expectations,
            postprocessor_failure=self.postprocessor_failure,
            postprocessor_failure_message=self.postprocessor_failure_message,
            log_text=log_text,
            result=self.get_assert_result(),
            elapsed_time=self.request_.elapsed_time,
        )

    def get_assert_result(self):
        """
        案例执行的断言结果
        :return: REPORT_RESULT
        """
        if self.expectations:
            result = all([self.expectations_result, not self.postprocessor_failure])
        else:
            result = not self.postprocessor_failure
        if result:
            return REPORT_RESULT.SUCCESS
        else:
            return REPORT_RESULT.FAILURE
